﻿#include "mytcpsocket.h"
#include "mypdu.h"
#include "myserver.h"
#include "mythread.h"
#include "filetrans_server.h"
#include "filetrans_socket.h"

MyTcpSocket::MyTcpSocket()
{
//    connect(this,&MyTcpSocket::readyRead,this,&MyTcpSocket::recvMsg);
//    connect(this,&MyTcpSocket::disconnected,this,&MyTcpSocket::handlerLogOut);
}

QString MyTcpSocket::getUserInfo()
{
    QString str = QString("%1").arg(m_u.name);
    return str;
}

void MyTcpSocket::recvMsg()
{
    PDU* pdu = makePDU(0);
    read((char*)pdu,pdu->maxSize);
    switch (pdu->msgType) {
    case RES://注册处理
        handleRegister();
        break;
    case LOG_IN://登陆处理
        handleLogin();
        break;
    case ADD_FRIEND://加好友请求处理
        handleAddFriend(pdu->friendId);
        break;
    case ADD_FRIEND_S://加好友同意处理
        handleAddFriendAgree(pdu);
        break;
    case MSG_SEND://有客户端给客户端发消息
        handleTransMsg();
        break;
    case FILE_REQUEST://有客户端给客户端发送了文件传输请求
        //文件请求需要另开socket 以免混淆数据
        handleTransFile();
        break;
    case FILE_RESPOND_AGREE://转发同意接受文件
    {
        userInfo u;
        memset(&u,0,sizeof (u));
        read((char*)&u,sizeof (u));
        MyServer::getInstance().transmitOnline(FILE_RESPOND_AGREE,this,u);
        break;
    }
    case SECURE_REQUEST://密保问题请求
        handleFindPwd(pdu);
        break;
    case RESET_PWD://重置密码请求
        handlerResetPwd(pdu);
        break;
    case FIND_INFO://查找个人信息
        //handlerFindInfo(pdu);
        break;
    case SEND_MOVE: //处理抖动
    {
        userInfo u;
        memset(&u,0,sizeof (u));
        read((char*)&u,sizeof (u));
        MyServer::getInstance().transmitOnline(SEND_MOVE,this,u);
        break;
    }
    case MEDIA_REQUEST://视频请求
    {
        userInfo u;
        memset(&u,0,sizeof (u));
        read((char*)&u,sizeof (u));
        MyServer::getInstance().transmitOnline(MEDIA_REQUEST,this,u);
        break;
    }
    case MEDIA_REQUEST_AGREE://视频请求同意
    {
        userInfo u;
        memset(&u,0,sizeof (u));
        read((char*)&u,sizeof (u));
        MyServer::getInstance().transmitOnline(MEDIA_REQUEST_AGREE,this,u);
        break;
    }
    case MEDIA_REQUEST_REFUSE://视频请求拒绝
    {
        userInfo u;
        memset(&u,0,sizeof (u));
        read((char*)&u,sizeof (u));
        MyServer::getInstance().transmitOnline(MEDIA_REQUEST_REFUSE,this,u);
        break;
    }
    case REQUEST_OFFLINELOG://查找离线消息文件
    {
        handlerOffLineLog(pdu);
        break;
    }
    case REG_GROUP:
    {
        handlerRegGroup();
        break;
    }
    case GROUP_ADDPERSON://群添加新成员消息
    {
        OpDb::getInstance().addFriendToGroup(pdu->friendId,pdu->data);
        break;
    }
    case LOAD_GROUP_PERSON://加载群成员
    {
        handlerLoadGPerson(pdu->friendId);
        break;
    }
    case GROUP_MSG:
    {
        handlerGroupMsg(pdu);
        break;
    }
    case GROUP_NOTIFY:
    {
        QByteArray qba = readAll();
        QString str(qba);
        OpDb::getInstance().updateGroupNotify(str,pdu->friendId);
        break;
    }
    case LOAD_GROUP_RECORD://获取群聊天记录
    {
        QString filepath = QString("D:\\ChatRecord\\%1.txt").arg(pdu->friendId);
        QFile file(filepath);
        if(file.open(QIODevice::ReadOnly))
        {
            QByteArray qba = file.readAll();
            write((char*)pdu,pdu->maxSize);
            write(qba);
        }
        break;
    }
//    case GROUP_FILE://获取群文件数据
//    {
//        char buff[1024];
//        read(buff,1024);
//        m_file.write(buff,1024);
//        break;
//    }
//    case GROUP_FILE2://群文件传输完毕
//    {
//        m_file.close();
//        break;
//    }
//    case GROUP_FILE3://群文件传输开始
//    {
//        QByteArray qba = readAll();
//        QString name(qba);
//        QString filename = QString("D:\\ChatClientInfo\\gf%1\\%2").arg(pdu->friendId).arg(name);
//        m_file.open(QIODevice::WriteOnly);
//        break;
//    }
    default:
        break;
    }

}

void MyTcpSocket::handlerLogOut()
{
    OpDb::getInstance().handlerLogOut(m_u);//数据库操作
    emit LogOut(this);
}

void MyTcpSocket::handleRegister()
{
    userInfo u;
    memset(&u,0,sizeof (u));
    read((char*)&u,sizeof (u));
    char buff[100]={0};
    read(buff,100);
    qDebug()<<u.name<<u.pwd<<endl;
    qDebug()<<buff<<endl;
    int id;
    if(!OpDb::getInstance().addUser(u,id,buff))
    {
        PDU* pdu = makePDU(0);
        pdu->msgType = RES_F;
        write((char*)pdu,pdu->maxSize);
        free(pdu);
        pdu=NULL;
        return;
    }
    else
    {
        PDU* pdu = makePDU(0);
        pdu->msgType = RES_S;
        pdu->dataSize = id;//将账号传过去
        write((char*)pdu,pdu->maxSize);
        free(pdu);
        pdu=NULL;
        return;
    }
}

void MyTcpSocket::handleLogin()
{
    userInfo u;
    memset(&u,0,sizeof (u));
    read((char*)&u,sizeof (u));//读取用户名和密码
    qDebug()<<u.name<<u.pwd;
    if(!OpDb::getInstance().selectUser(u))
    {
        PDU* pdu = makePDU(0);
        pdu->msgType = LOG_IN_F;
        write((char*)pdu,pdu->maxSize);
        free(pdu);
        pdu=NULL;
        return;
    }
    else
    {
        PDU* pdu = makePDU(0);
        pdu->msgType = LOG_IN_S;
        write((char*)pdu,pdu->maxSize);
        free(pdu);
        pdu=NULL;
        m_u=u;//m_u  记录用户的信息

        //获取好友信息并发送
        QList<userInfo> listU =  OpDb::getInstance().selectOnlineFriend(u);
        int len = listU.size();
        write((char*)&len,4);
        for(int i=0;i<len;++i)
        {
            userInfo u = listU[i];
            write((char*)&u,sizeof (u));
        }
        //获取群聊信息并发送
        QList<QString> list2 = OpDb::getInstance().selectGroup(u.name);
        len = list2.size();
        write((char*)&len,4);
        for(int i=0;i<len;++i)
        {
            groupinfo info;
            memset(&info,0,sizeof (info));
            QString gname = OpDb::getInstance().getGroupName(list2[i]);
            QString ghead = OpDb::getInstance().getGroupHead(list2[i]);
            strcpy(info.gid,list2[i].toStdString().c_str());
            strcpy(info.gname,gname.toStdString().c_str());
            strcpy(info.ghead,ghead.toStdString().c_str());
            write((char*)&info,sizeof (info));
        }
        //向别人发送自己已经上线
        MyServer::getInstance().transmitOnline(ONLINE,this,u);
    }
}

void MyTcpSocket::handleAddFriend(const char* name)
{
    userInfo u;
    memset(&u,0,sizeof (u));
    read((char*)&u,sizeof (u));
    strcpy(m_addU.name,u.name);
    MyServer::getInstance().handleAddFriend(name,u);
}

void MyTcpSocket::handleAddFriendAgree(PDU* pdu)
{
    userInfo u;
    memset(&u,0,sizeof (u));
    read((char*)&u,sizeof (u));
    userInfo src;
    //这里让src.name为发送好友请求的人  src.pwd为接收好友请求的人
    strcpy(src.name,pdu->friendId);
    strcpy(src.pwd,u.name);
    OpDb::getInstance().addFriend(pdu->friendId,u.name);
    MyServer::getInstance().transmitOnline(ADD_FRIEND_S,this,src);//向添加者发送添加成功
}

void MyTcpSocket::handleTransMsg()
{
    userInfo u;
    memset(&u,0,sizeof (u));
    read((char*)&u,sizeof (u));
    char msg[1024];
    memset(msg,0,1024);
    read(msg,1024);
    MyServer::getInstance().transmitOnline(MSG_SEND,this,u,msg);
}

void MyTcpSocket::handleTransFile()
{
    //获取文件接收方和发送方
    userInfo u;
    memset(&u,0,sizeof (u));
    read((char*)&u,sizeof (u));
    //转发请求
    MyServer::getInstance().transmitOnline(FILE_REQUEST,this,u);
}

void MyTcpSocket::handleFindPwd(PDU *pdu)
{
    char username[15]={0};
    char anser2[20]={0};
    memcpy(username,pdu->friendId,11);
    strncpy(anser2,pdu->friendId+13,19);
    QString anser;
    anser = OpDb::getInstance().handlerFindPwd(QString::fromStdString(username));
    if(strcmp(anser.toStdString().c_str(),anser2)==0)
    {
        PDU* pdu = makePDU(0);
        pdu->msgType = SECURE_RESPOND_S;
        write((char*)pdu,pdu->maxSize);
        delete pdu;
        pdu = nullptr;
    }
    else
    {
        PDU* pdu = makePDU(0);
        pdu->msgType = SECURE_RESPOND_F;
        write((char*)pdu,pdu->maxSize);
        delete pdu;
        pdu = nullptr;
    }

}

void MyTcpSocket::handlerResetPwd(PDU *pdu)
{
    PDU* pdu1 = makePDU(0);
    if(OpDb::getInstance().ResetPwd(pdu))
    {
        pdu1->msgType = RESET_PWD_S;
    }
    else
        pdu1->msgType = RESET_PWD_F;
    write((char*)pdu1,pdu1->maxSize);
    delete pdu1;
    pdu1 = nullptr;
}

void MyTcpSocket::handlerFindInfo(PDU *pdu)
{
    QString name(pdu->friendId);
    QString uinfo = OpDb::getInstance().getUserInfo(name);
    PDU* pdu1 = makePDU(0);
    pdu1->msgType=FIND_INFO;
    pdu1->dataSize=uinfo.toStdString().length();
    write((char*)pdu1,pdu1->maxSize);
    write(uinfo.toStdString().c_str(),pdu1->dataSize);
    free(pdu);
}

void MyTcpSocket::handlerOffLineLog(PDU *pdu)
{
    QString filename = QString("D:\\ChatRecord\\%1.txt").arg(getUserInfo());
    QFile file(filename);
    if(file.exists())
    {
        if(file.open(QIODevice::ReadOnly))
        {
            QByteArray ba = file.readAll();
            write((char*)pdu,pdu->maxSize);
            write(ba);
        }
        file.close();
        QFile file2(filename);
        file2.open(QIODevice::WriteOnly|QIODevice::Truncate);
        file2.close();
        delete pdu;
        pdu = nullptr;
    }
}

void MyTcpSocket::handlerRegGroup()
{
    userInfo u;
    memset(&u,0,sizeof (u));
    read((char*)&u,sizeof (u));
    QString groupid;
    if(true==OpDb::getInstance().registerGroup(u.name,groupid,u))
    {
        PDU* pdu = makePDU(0);
        pdu->msgType = REG_GROUP_S;
        QString groupname = OpDb::getInstance().getGroupName(groupid);
        QString grouphead = OpDb::getInstance().getGroupHead(groupid);
        strcpy(pdu->friendId,groupname.toStdString().c_str());
        strcpy(pdu->data,grouphead.toStdString().c_str());
        pdu->dataSize = groupid.toUInt();
        MyServer::getInstance().transmitGroupRegS(pdu,u);
        QString file1 = QString("D:\\ChatClientInfo\\gf%1").arg(groupid);
        QString file2 = QString("D:\\ChatClientInfo\\gp%1").arg(groupid);
        QString file3 = QString("D:\\ChatClientInfo\\gi%1").arg(groupid);
        QDir dir(file1);
        if(!dir.exists())
        {
            dir.mkdir(file1);
        }
        QDir dir2(file2);
        if(!dir2.exists())
        {
            dir2.mkdir(file2);
        }
        QDir dir3(file3);
        if(!dir3.exists())
        {
            dir3.mkdir(file3);
        }
        delete pdu;
        pdu = nullptr;
    }
}

void MyTcpSocket::handlerLoadGPerson(QString gname)
{
    QList<QPair<QString,int>> list = OpDb::getInstance().getGroupPerson(gname);
    PDU* pdu = makePDU(0);
    pdu->msgType = LOAD_GROUP_PERSON;
    write((char*)pdu,pdu->maxSize);
    int len = list.size();
    write((char*)&len,4);
    for(auto x : list)
    {
        userInfo3 u3;
        QString info = x.first;
        QString online =QString("%1").arg(x.second);
        strcpy(u3.uname,online.toStdString().c_str());
        strcpy(u3.uhead,info.toStdString().c_str());
        write((char*)&u3,sizeof (u3));
    }
    delete pdu;
    pdu = nullptr;
}

void MyTcpSocket::handlerGroupMsg(PDU* pdu)
{
    userInfo u;
    read((char*)&u,sizeof (u));
    char msg[1024]={0};
    read(msg,1024);
    //每次收到群消息就保存到日志
    QString gid(pdu->friendId);
    int i = gid.indexOf('(');
    gid =gid.replace(")","");
    gid = gid.mid(i+1);
    QString filepath = QString("D:\\ChatRecord\\%1.txt").arg(gid);
    QFile file(filepath);
    if(file.open(QIODevice::Append|QIODevice::WriteOnly))
    {
        QDateTime current_date_time = QDateTime::currentDateTime();
        QString current_date;
        current_date = QString(u.name) +"&" + current_date_time.toString("yyyy-MM-dd hh:mm::ss");
        current_date+="\r\n";
        file.write(current_date.toStdString().c_str());
        QString Msg(msg);
        Msg = "わ" + Msg + "わ\r\n";
        file.write(Msg.toStdString().c_str());
        file.close();
    }
    MyServer::getInstance().transmitGroupMsg(pdu,u,msg,this);
}

QList<userInfo> MyTcpSocket::selectFriend(MyTcpSocket* sock,userInfo u)//查找在线好友
{
    QList<userInfo> listU = OpDb::getInstance().selectOnlineFriend(u);
    int len = listU.size();
    sock->write((char*)&len,4);
    for(int i=0;i<len;++i)
    {
        userInfo tu = listU[i];
        sock->write((char*)&tu,sizeof (tu));
    }
    return listU;
}

MyTcpSocket &MyTcpSocket::getInstance()
{
    static MyTcpSocket sock;
    return sock;
}
